home *** CD-ROM | disk | FTP | other *** search
/ PC Graphics Unleashed / PC Graphics Unleashed.iso / ch05 / dither.old < prev    next >
Text File  |  1994-07-31  |  10KB  |  253 lines

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<conio.h>
  4. #include<fcntl.h>
  5. #include<io.h>
  6. #include<vsa.h>
  7. #include<vsa_font.h>
  8. #include<tiff.h>
  9.  
  10. void     draw_dithered_pixel(int,int,unsigned char *,int);
  11. int      crack_rgb(unsigned char *,int *,int *,int *,float *,
  12.                                      float *,float *);
  13. unsigned long read_tga_header(int,int *,int *,int *,int *);
  14. void     true_color_lut(void);
  15.  
  16.  
  17. unsigned char dither[4][64]={
  18. {
  19.  1 },
  20. {
  21.  1, 3,
  22.  4, 2 },
  23. {
  24.  1,  9, 3, 11,
  25. 13,  5, 15, 7,
  26.  4, 12, 2, 10,
  27. 16,  8, 14, 6 },
  28. {
  29.  1, 33,  9, 41,  3, 35, 11, 43,
  30. 49, 17, 57, 25, 51, 19, 59, 27,
  31. 13, 45,  5, 37, 15, 47,  7, 39,
  32. 61, 29, 53, 21, 63, 31, 55, 23,
  33.  4, 36, 12, 44,  2, 34, 10, 42,
  34. 52, 20, 60, 28, 50, 18, 58, 26,
  35. 16, 48,  8, 40, 14, 46,  6, 38,
  36. 64, 32, 56, 24, 62, 30, 54, 22 },
  37. };
  38.  
  39. /*......................... DITHER.C............. 5-29-94 .....*/
  40. /* This program reads True Color (24 bit per pixel) TARGA      */
  41. /* images and converts them to 8 bit dithered screen images.   */
  42. /* It also writes out the dithered image as an 8 bit per pixel */
  43. /* Palette Color TIFF image.                                   */
  44. /*.............................................................*/
  45. void main()
  46. {
  47.   char filename[80];
  48.   int i,j,size,width,height,type,file_handle,orient;
  49.   unsigned char rgb[3072];
  50.     printf("Input TARGA Image Filename: ");
  51.   scanf("%s",filename);
  52. LOOP:
  53. /*.............................................................*/
  54. /* Get dither size and limit it to legal value of 1,2,4 or 8.  */
  55. /*.............................................................*/
  56.   printf("Input Dither Size (1, 2, 4, or 8): ");
  57.   scanf("%d",&size);
  58.   if(size == 3) size = 4;     /* size limited to 1, 2, 4, or 8 */
  59.   if(size > 4)  size = 8;     /* size limited to 1, 2, 4, or 8 */
  60. /*.............................................................*/
  61. /*            Set highest video resolution available.          */
  62. /*.............................................................*/
  63.     if(vsa_init(0x2105) != 0)                /* 1024 x 768 x 256 */
  64.     if(vsa_init(0x2103) != 0)              /*  800 x 600 x 256 */
  65.       if(vsa_init(0x2101) != 0)            /*  640 x 480 x 256 */
  66.         if(vsa_init(0x2100) != 0)          /*  640 x 400 x 256 */
  67.           {
  68.             printf("Can't set VESA video mode\n");
  69.             printf("Is VESA BIOS Extension TSR loaded?\n");
  70.             return;
  71.           }
  72. /*.............................................................*/
  73. /*           Open the TARGA file and get header info.          */
  74. /*.............................................................*/
  75.   if((file_handle = open(filename,O_BINARY | O_RDONLY)) == -1)
  76.         return;
  77.   read_tga_header(file_handle,&width,&height,&type,&orient);
  78. /*.............................................................*/
  79. /*       Set up the Palette as an 8 bit RGB (3,3,2) table.     */
  80. /*.............................................................*/
  81.   true_color_lut();
  82. /*.............................................................*/
  83. /*  Read out pixels from TARGA file and plot on screen in      */
  84. /*  top down or bottom up order depending on orientation.      */
  85. /*.............................................................*/
  86.   if(orient == 32)
  87.     for(j=0;j<height;j++)
  88.       {
  89.                 read(file_handle,rgb,3*width);
  90.         for(i=0;i<width;i++)
  91.           draw_dithered_pixel(i,j,rgb+3*i,size);
  92.       }
  93.   else
  94.     for(j=height-1;j>=0;j--)
  95.       {
  96.         read(file_handle,rgb,3*width);
  97.         for(i=0;i<width;i++)
  98.           draw_dithered_pixel(i,j,rgb+3*i,size);
  99.       }
  100. /*.............................................................*/
  101. /*  Close the image file and look for an ESC key to quit.      */
  102. /*  Otherwise, save dithered image as an 8 bit TIFF called     */
  103. /*  NEW.TIF and LOOP for experimentation with a different      */
  104. /*  dither box size.                                           */
  105. /*.............................................................*/
  106.   close(file_handle);
  107.   if(getch() == 27)
  108.     goto SKIP;
  109.   tf_save_file(0,0,width-1,height-1,"new.tif");
  110.   vsa_set_svga_mode(0x3);
  111.   goto LOOP;                    /*.....   Oh No, a goto!  .....*/
  112. SKIP:
  113.   vsa_set_svga_mode(0x3);
  114.   return;                       /*.....   End main        .....*/
  115. }
  116.  
  117. /*.................... DRAW_DITHERED_PIXEL ....... 5-27-94 ....*/
  118. /* This routine draws a dithered pixel at screen coordinate    */
  119. /* 'i,j' with 24 bit color equivalent passed in the 3 byte     */
  120. /* array 'rgb'.  The dither pattern size is specified by 'size'*/
  121. /* and can be 1, 2, 4, or 8.  Note that the global 'dither'    */
  122. /* array must must be initialized before calling this routine. */
  123. /*.............................................................*/
  124. void draw_dithered_pixel(int i,int j,unsigned char *rgb,int size)
  125. {
  126.   int n,m,q,r,red_lvl,grn_lvl,blu_lvl;
  127.   int color,red_boost,grn_boost,blu_boost;
  128.     float x,y,frl,fgl,fbl;
  129. /*.............................................................*/
  130. /* For the pixels screen address i,j, compute pixel address r  */
  131. /* within the dither box.  Also select dither box q based on   */
  132. /* size (size = 1, 2, 4, or 8).                                */
  133. /*.............................................................*/
  134.   x = (float)i/size;
  135.   y = (float)j/size;
  136.   m = (int)(size*(x - (int)x) + 0.5);
  137.   n = (int)(size*(y - (int)y) + 0.5);
  138.   q = size/2;
  139.   if(size == 8) q = 3;
  140.   r = m+n*size;
  141. /*.............................................................*/
  142. /* Get the Dark Pixel color, the Light Pixel components, and   */
  143. /* the pixel color errors.                                     */
  144. /*.............................................................*/
  145.   color = crack_rgb(rgb,&red_boost,&grn_boost,&blu_boost,
  146.                     &frl,&fgl,&fbl);
  147. /*.............................................................*/
  148. /*Scale the pixel color error values based on dither box size  */
  149. /*.............................................................*/
  150.   red_lvl = size*size*frl;
  151.   grn_lvl = size*size*fgl;
  152.   blu_lvl = size*size*fbl;
  153. /*.............................................................*/
  154. /*Test the pixels red, green, and blue error values against the*/
  155. /*thresholds in the dither box.  Decide which color to use.    */
  156. /*.............................................................*/
  157.   if(dither[q][r] <= red_lvl)
  158.     color = (color & 0x1f) + (red_boost << 5);    /* Boost Red */
  159.   if(dither[q][r] <= grn_lvl)
  160.     color = (color & 0xe3) + (grn_boost << 2);    /* Boost Grn */
  161.   if(dither[q][r] <= blu_lvl)
  162.     color = (color & 0xfc) + blu_boost;           /* Boost Blu */
  163. /*.............................................................*/
  164. /*              Set color and draw pixel on screen.            */
  165. /*.............................................................*/
  166.   vsa_set_color(color);
  167.     vsa_set_pixel(i,j);
  168.   return;
  169. }                           /*.... END draw_dithered_pixel ....*/
  170.  
  171.  
  172. /*.......................... CRACK_RGB ........... 5-27-94 ....*/
  173. /* This routine takes the 24 bit RGB color value in the 'rgb'  */
  174. /* array, quantizes it down to an 8 bit color value (3 bit red,*/
  175. /* 3 bit green, and 2 bit blue) and returns this 8 bit         */
  176. /* 'base_color' value. It also computes the 8 bit color boost  */
  177. /* values '*red_boost', 'grn_boost', and 'blu_boost' which are */
  178. /* used to draw dithered pixels.  It also computes the color   */
  179. /* error values 'red_lvl', 'grn_lvl', and 'blu_lvl' which      */
  180. /* determine when the dither function draws with 'base_color'  */
  181. /* and when it draws with 'xxx_boost' color.                   */
  182. /*.............................................................*/
  183. int crack_rgb(unsigned char *rgb,int *red_boost,int *grn_boost,
  184.               int *blu_boost,float *red_lvl,float *grn_lvl,
  185.               float *blu_lvl)
  186. {
  187.   int   base_color,red,grn,blu;
  188.   float fred,fgrn,fblu;
  189.  
  190.   fred = rgb[2]/36.6;   /*36.6 = (256 shades of red)/(2^3 - 1) */
  191.   fgrn = rgb[1]/36.6;   /*36.6 = (256 shades of grn)/(2^3 - 1) */
  192.   fblu = rgb[0]/85.4;   /*85.4 = (256 shades of blu)/(2^2 - 1) */
  193.  
  194.   red = fred;
  195.   grn = fgrn;
  196.   blu = fblu;
  197.   base_color = (red << 5)+(grn << 2)+blu;   /*Dark Pixel color */
  198.  
  199.   *red_lvl = fred - red;
  200.   *grn_lvl = fgrn - grn;
  201.   *blu_lvl = fblu - blu;
  202.  
  203.   *red_boost = red+1;  /*This is the Light Pixel color for red */
  204.   *grn_boost = grn+1;  /*This is the Light Pixel color for grn */
  205.   *blu_boost = blu+1;  /*This is the Light Pixel color for blu */
  206.  
  207.   return base_color;
  208. }                           /*.... END crack_rgb          .....*/
  209.  
  210.  
  211. /*....................... READ_TGA_HEADER  ....... 5-17-94 ....*/
  212. /* This routine parses through a TGA header and returns the    */
  213. /* file offset in bytes to the first byte of pixel data.       */
  214. /* It also returns image width, height, and type (type 2 is the*/
  215. /* uncompressed 24 bit image type).                            */
  216. /*.............................................................*/
  217. unsigned long read_tga_header(int handle, int *width,
  218.                               int *height, int *type,
  219.                                                             int *orientation)
  220. {
  221.   unsigned long offset;
  222.   unsigned char buff[18];
  223.   read(handle,buff,18);
  224.   offset = 18+buff[0];
  225.   *type = buff[2];
  226.  
  227.   *width  = *((unsigned *)buff + 6);
  228.   *height = *((unsigned *)buff + 7);
  229.     *orientation = buff[17];
  230.     return offset;
  231. }                           /*.... END read_tga_header    .....*/
  232.  
  233. /*.................... TRUE_COLOR_LUT.C .......... 5-15-94 ....*/
  234. /* This routine generates a 'true color' LUT.  An 8 bit index  */
  235. /* into the LUT represents 3 bits of RED, 3 bits of GREEN, and */
  236. /* 2 bits of BLUE.  The 3 msbs of the 8 bit index are the RED  */
  237. /* field, next 3 are GREEN, and the 2 lsbs are the BLUE field. */
  238. /*                                                             */
  239. /*.............................................................*/
  240. void true_color_lut(void)
  241. {
  242.     int i;
  243.     unsigned char color_array[768];
  244.     for(i=0;i<256;i++)
  245.         {
  246.             color_array[3*i+0]= ((i & 0x00e0) >> 5) * 9;
  247.             color_array[3*i+1]= ((i & 0x001c) >> 2) * 9;
  248.             color_array[3*i+2]= (i & 0x0003) * 21;
  249.         }
  250.     vsa_write_color_block(0,256,color_array);
  251.     return;
  252. }                          /*.....   End true_color_lut   .....*/
  253.